package cn.zhaosunny.soap

import kotlinx.coroutines.Dispatchers
import java.lang.reflect.Method
import kotlin.coroutines.Continuation
import kotlin.coroutines.intrinsics.COROUTINE_SUSPENDED
import kotlin.coroutines.intrinsics.intercepted
import kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn
import kotlin.coroutines.resumeWithException

/**
 *
 * @author zhaoyang 2021/12/6
 */
//suspend fun CallFactory.await(): Any {
//    val that = this
//    return suspendCancellableCoroutine { continuation ->
//        val result = call(that.soap!!, that.soapRequest!!)
//        continuation.resume(soap!!.convertResult(result, that.kotinRawType!!))
//    }
//}

internal fun isKotlinCall(method: Method): Boolean {
    return method.parameterTypes.last() == Continuation::class.java
}

/**
 * Force the calling coroutine to suspend before throwing [this].
 *
 * This is needed when a checked exception is synchronously caught in a [java.lang.reflect.Proxy]
 * invocation to avoid being wrapped in [java.lang.reflect.UndeclaredThrowableException].
 *
 * The implementation is derived from:
 * https://github.com/Kotlin/kotlinx.coroutines/pull/1667#issuecomment-556106349
 */
internal suspend fun Exception.suspendAndThrow(): Nothing {
    suspendCoroutineUninterceptedOrReturn<Nothing> { continuation ->
        Dispatchers.Default.dispatch(continuation.context, Runnable {
            continuation.intercepted().resumeWithException(this@suspendAndThrow)
        })
        COROUTINE_SUSPENDED
    }
}